package vip.aster.quartz.utils;

import cn.hutool.core.bean.BeanUtil;
import org.apache.commons.lang3.StringUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import vip.aster.common.constant.Constants;
import vip.aster.common.utils.ExceptionUtils;
import vip.aster.common.utils.SpringUtils;
import vip.aster.quartz.constant.ScheduleConstants;
import vip.aster.quartz.entity.ScheduleJob;
import vip.aster.quartz.entity.ScheduleJobLog;
import vip.aster.quartz.service.ScheduleJobLogService;

import java.time.LocalDateTime;
import java.util.Date;

/**
 * 抽象quartz调用
 *
 * @author Aster
 * @since 2024/3/6 14:33
 */
public abstract class AbstractQuartzJob implements Job {
    private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);

    /**
     * 线程本地变量
     */
    private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        ScheduleJob scheduleJob = new ScheduleJob();
        BeanUtil.copyProperties(context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES), scheduleJob, true);
        try {
            before(context, scheduleJob);
            doExecute(context, scheduleJob);
            after(context, scheduleJob, null);
        } catch (Exception e) {
            log.error("任务执行异常  - ：", e);
            after(context, scheduleJob, e);
        }
    }

    /**
     * 执行前
     *
     * @param context     工作执行上下文对象
     * @param scheduleJob 系统计划任务
     */
    protected void before(JobExecutionContext context, ScheduleJob scheduleJob) {
        threadLocal.set(new Date());
    }

    /**
     * 执行后
     *
     * @param context     工作执行上下文对象
     * @param scheduleJob 系统计划任务
     */
    protected void after(JobExecutionContext context, ScheduleJob scheduleJob, Exception e) {
        Date startTime = threadLocal.get();
        threadLocal.remove();

        final ScheduleJobLog jobLog = new ScheduleJobLog();
        jobLog.setJobId(scheduleJob.getId());
        jobLog.setJobName(scheduleJob.getJobName());
        jobLog.setJobGroup(scheduleJob.getJobGroup());
        jobLog.setInvokeTarget(scheduleJob.getInvokeTarget());
        long runMs = startTime.getTime() - new Date().getTime();
        jobLog.setJobMessage(jobLog.getJobName() + " 总共耗时：" + runMs + "毫秒");
        if (e != null) {
            jobLog.setStatus(Constants.FAIL);
            String errorMsg = StringUtils.substring(ExceptionUtils.getExceptionMessage(e), 0, 2000);
            jobLog.setExceptionInfo(errorMsg);
        } else {
            jobLog.setStatus(Constants.SUCCESS);
        }

        // 写入数据库当中
        SpringUtils.getBean(ScheduleJobLogService.class).save(jobLog);
    }

    /**
     * 执行方法，由子类重载
     *
     * @param context     工作执行上下文对象
     * @param scheduleJob 系统计划任务
     * @throws Exception 执行过程中的异常
     */
    protected abstract void doExecute(JobExecutionContext context, ScheduleJob scheduleJob) throws Exception;
}
